package gin

import (
	"context"
	"net/http"
	"sync"
	"time"

	"gitee.com/zacyuan/yuan/pkg/config"
	"gitee.com/zacyuan/yuan/pkg/log"
	"github.com/gin-gonic/gin"
)

const (
	httpReadTimeout   = 20 * time.Second
	httpWriteTimeout  = 20 * time.Second
	idleTimeout       = 5 * time.Minute
	defaultConfigHost = "host"
)

type Gin struct {
	once  sync.Once
	eng   *Engine
	svr   *http.Server
	hooks []Hook
}

func NewGinServer() *Gin {
	server := new(Gin)
	server.eng = gin.New()
	server.svr = &http.Server{ReadTimeout: httpReadTimeout, WriteTimeout: httpWriteTimeout, IdleTimeout: idleTimeout}
	server.svr.Handler = server.eng
	return server
}

func (s *Gin) Host(host string) *Gin {
	s.svr.Addr = host
	return s
}

func (s *Gin) Start(ctx context.Context) error {
	s.once.Do(func() {
		if s.svr.Addr == "" {
			s.svr.Addr = config.GetString("host")
			if s.svr.Addr == "" {
				s.svr.Addr = ":8008"
			}
		}

		go func() {
			// 服务连接
			if err := s.svr.ListenAndServe(); err != nil && err != http.ErrServerClosed {
				log.Panicf("listen: %s\n", err.Error())
			}
		}()
	})

	return nil
}

func (s *Gin) Stop(ctx context.Context) error {
	if err := s.svr.Shutdown(ctx); err != nil {
		return err
	}
	return nil
}

func (s *Gin) Restart(ctx context.Context) error {
	return nil
}

func (s *Gin) RegisterController(relativePath string, ctls []any, hooks ...Hook) {
	var router IRoutes = s.eng
	if relativePath != "" && relativePath != "/" {
		if relativePath[0] != '/' {
			relativePath = "/" + relativePath
		}

		router = s.eng.Group(relativePath)
	}

	hooks = append(s.hooks, hooks...)
	RegisterController(router, ctls, hooks...)
}

func (s *Gin) GetEngine() *Engine {
	return s.eng
}

func (s *Gin) AddHook(hooks ...Hook) {
	s.hooks = append(s.hooks, hooks...)
}
